package edu.cmu.ece.ds.droidchat;

import java.io.IOException;
import java.net.MalformedURLException;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.facebook.android.DialogError;
import com.facebook.android.Facebook;
import com.facebook.android.Facebook.DialogListener;
import com.facebook.android.FacebookError;

import edu.cmu.ece.ds.droidchat.NetworkService.LocalBinder;
import edu.cmu.ece.ds.droidchat.message.ClientLoginResponseMessage;
import edu.cmu.ece.ds.droidchat.model.StringConstants;

public class LogInActivity extends Activity {
    private final String TAG = "LogInActivity";

    // facebook object
    private Facebook facebook = Toolbox.getFacebookObject();

    // Layout Views
    private Button mLoginButton;
    private TextView mUsername;
    private TextView mPassword;
    private ImageView mFbImage;
    private TextView mInfoText;

    NetworkService mService; // the Service component
    private boolean mBound = false;
    private ServiceMessageReceiver mReceiver; // the BroadcastReceiver component
    // Intent request codes
    private static final int REQUEST_REGISTRATION = 1;

    // Dialog IDs
    static final int DIALOG_LOGIN_PAUSED_ID = 0;

    // Progress Dialogs
    private ProgressDialog login_dialog;
    private boolean isLoggingIn = false;

    // The action listener for the EditText widget, to listen for the return key
    private TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() {
        public boolean onEditorAction(TextView view, int actionId,
                KeyEvent event) {
            // If the action is a key-up event on the return key, send the
            // message
            if (actionId == EditorInfo.IME_NULL
                    && event.getAction() == KeyEvent.ACTION_UP) {
                Log.i(TAG, "Enter Key is pressed");
            }
            return true;
        }
    };

    private class ServiceMessageReceiver extends BroadcastReceiver {
        public static final String TAG = "ServerMessageReceiver";

        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "onReceive: " + intent);
            String userid = intent
                    .getStringExtra(StringConstants.EXTRA_USER_NAME);
            int response = intent
                    .getIntExtra(StringConstants.EXTRA_RESPONSE, 0);
            Log.d(TAG, "userid: " + userid);
            Log.d(TAG, "response: " + response);

            if (isLoggingIn) {
                login_dialog.dismiss();

                if (response == ClientLoginResponseMessage.NO_USER) {
                    Toast.makeText(
                            getApplicationContext(),
                            "Login request with userid='"
                                    + userid
                                    + "' was NOT successful because username is not registered!",
                            Toast.LENGTH_LONG).show();
                } else if (response == ClientLoginResponseMessage.WRONG_PASSWORD) {
                    Toast.makeText(
                            getApplicationContext(),
                            "Login request with userid='"
                                    + userid
                                    + "' was NOT successful because password is wrong!",
                            Toast.LENGTH_LONG).show();
                } else {
                    // successful login
                    startDroidChatTabActivity(userid);
                    Log.d(TAG, "calling finish()");
                    finish(); // once the DroidChatTabActivity is started
                    		  //  it means the user has logged in
                    		  //  let's destroy the LogInActivity
                }
            }// else i really don't care
        }
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);
        Log.d(TAG, "---onCreate---");

        mLoginButton = (Button) findViewById(R.id.login_button);
        mUsername = (EditText) findViewById(R.id.user_id);
        mPassword = (EditText) findViewById(R.id.password);
        mFbImage = (ImageView) findViewById(R.id.fb_button);
        mInfoText = (TextView) findViewById(R.id.info);

        // Initialize the username and password field with a listener for the
        // "return key"
        mUsername.setOnEditorActionListener(mWriteListener);
        mPassword.setOnEditorActionListener(mWriteListener);
        mReceiver = new ServiceMessageReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(StringConstants.ACTION_CLIENT_LOGIN_RESPONSE);
        this.registerReceiver(mReceiver, filter);
        Log.d(TAG, "ServerMessageReceiver registered! ");
        mFbImage.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (!facebook.isSessionValid()) {
                    facebook.authorize(LogInActivity.this,
                            new DialogListener() {
                                @Override
                                public void onComplete(Bundle values) {
                                    // TODO: handle them in a separate thread
                                    startDroidChatTabActivityWithFb();
                                }

                                @Override
                                public void onFacebookError(FacebookError error) {
                                }

                                @Override
                                public void onError(DialogError e) {
                                }

                                @Override
                                public void onCancel() {
                                }
                            });
                } else {
                    Log.e(TAG, "HEY! Session still valid");
                    startDroidChatTabActivityWithFb();
                }
            }
        });

        // debug only.
        mInfoText.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent i = new Intent(LogInActivity.this,
                        DroidChatTabActivity.class);
                startActivity(i);
            }
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, "---onStart---");

        Intent intent = new Intent(this, NetworkService.class);
        Log.d(TAG, "calling bindService()");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        // Initialize the send button with a listener that for click events
        mLoginButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {

                // Opens Socket to contact the servers
                Log.d(TAG, "Login Button is pressed");

                if (mUsername.getText().toString().length() == 0) {
                    Log.d(TAG, "username is not entered");
                    Toast.makeText(getApplicationContext(),
                            R.string.login_error_none_entered,
                            Toast.LENGTH_SHORT).show();
                } else if (mPassword.getText().toString().length() == 0) {
                    Log.d(TAG, "password is not entered");
                    Toast.makeText(getApplicationContext(),
                            R.string.login_error_none_entered,
                            Toast.LENGTH_SHORT).show();
                } else {
                    Log.d(TAG, mUsername.getText().toString());
                    Log.d(TAG, mPassword.getText().toString());

                    if (mBound == true) {
                        if (mService.isConnectedToServer()) {
                            Log.d(TAG, "mBound is true");
                            isLoggingIn = true;
                            // asks the service to send ClientLoginMessage to
                            // the DroidChat server
                            mService.login(mUsername.getText().toString(),
                                    mPassword.getText().toString());

                            showDialog(LOGGINGIN_ID);
                        } else {
                            Toast.makeText(getApplicationContext(),
                                    R.string.login_error_server_down,
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            }
        });
    }

    public void onStop() {
        super.onStop();
        Log.d(TAG, "---onStop---");
        Log.d(TAG, "---calling unbindService---");
        unbindService(mConnection);
    }

    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "---onDestroy---");
        unregisterReceiver(mReceiver);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        facebook.authorizeCallback(requestCode, resultCode, data);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.d(TAG, "---onConfigurationChanged---");
        setContentView(R.layout.login);
    }

    private void startDroidChatTabActivity(String userid) {
        Intent i = new Intent(LogInActivity.this, DroidChatTabActivity.class);
        i.putExtra(StringConstants.EXTRA_USER_NAME, userid);
        startActivity(i);
    }

    private void startDroidChatTabActivity() {
        Intent i = new Intent(LogInActivity.this, DroidChatTabActivity.class);
        startActivity(i);
    }

    private void startDroidChatTabActivityWithFb() {
        try {
            String fbFriendList = facebook
                    .request(StringConstants.FACEBOOK_REQUEST_ME_FRIENDS);
            Toolbox.prepareFriendIds(fbFriendList);
            String fbMyInfoString = facebook
                    .request(StringConstants.FACEBOOK_REQUEST_ME);
            Log.e("fbMyInfoString", fbMyInfoString);
            Toolbox.prepareMyInfo(fbMyInfoString);
            startDroidChatTabActivity();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.login_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {

        case R.id.register_from_menu:
            // Launch the DeviceListActivity to see devices and do scan
            Intent serverIntent = new Intent(this, RegisterActivity.class);
            startActivityForResult(serverIntent, REQUEST_REGISTRATION);
            return true;
        }
        return false;
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to TCPService, cast the IBinder and get TCPService
            // instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
            Log.d(TAG, "We've bound to TCPService");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBound = false;
        }
    };

    static final int LOGGINGIN_ID = 0;

    protected Dialog onCreateDialog(int id) {
        Dialog dialog;
        switch (id) {
        case LOGGINGIN_ID:
            /*
             * AlertDialog.Builder builder = new AlertDialog.Builder(this);
             * builder.setMessage("Loggin In... Please Wait")
             * .setCancelable(false) // cannot be cancelled by the BACK key, use
             * 'ABORT' .setNegativeButton("Abort", new
             * DialogInterface.OnClickListener() {
             *
             * public void onClick(DialogInterface dialog, int which) {
             * dialog.cancel(); } }); dialog = builder.create();
             */
            login_dialog = login_dialog.show(LogInActivity.this, "",
                    "Logging in. Please Wait...");
            break;
        default:
            dialog = null;
        }
        // login_dialog = dialog;
        return login_dialog;
    }
}
